import axios from 'axios'
import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage } from "element-plus";
import { userStore } from "@/store/modules/user";
import router from '@/router';

const service: AxiosInstance = axios.create();
// 取消重复请求的接口
let cancelApiArray: ObjValueAny[] = [];

// 请求拦截（配置发送请求的信息）
interface InternalAxiosRequestConfigExtends extends InternalAxiosRequestConfig {
    noRepeat?: string | number
}

service.interceptors.request.use((config: InternalAxiosRequestConfigExtends): Promise<any> => {
    const { token } = userStore();
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    cancelApiArray = cancelApiArray.filter((row: ObjValueAny) => {
        // 自带怎么判断是同一个接口在重复请求  遍历这个数组如果请求方式和url一样就是同一个接口
        if (row.url === config.url && row.method === config.method && row.noRepeat === config.noRepeat) {
            // 确定是同一个接口调用取消方法
            row.fn()
            // 销毁数据 不然这个数组会越来越大
            // 符合这个要求的接口 调用取消axios方法后 不保留
            return false
        }
        // 不符合这个要求的接口 保留接口
        return true
    });
    config.cancelToken = new axios.CancelToken(cancelFn => {
        // config 把地址和方式存进数组中 方便后面判断 所有方法存进数组中
        const storeCancelApiArr = {
            url: config.url,
            noRepeat: config.noRepeat,
            method: config.method,
            fn: cancelFn
        }
        if (config.noRepeat) {
            cancelApiArray.push(storeCancelApiArr)
        }
    });
    return Promise.resolve(config);
}, error => {
    return Promise.reject(error);
})

let showMsg: boolean = true;
const layoutCode: number = 401;
service.interceptors.response.use((response: AxiosResponse): Promise<any> => {
    let { data, config }: ObjValueAny = response || {};
    if (data.code === layoutCode && !config.noRouter) {
        logoutMessage(data);
        return Promise.reject(data);
    }
    return Promise.resolve(data);
}, (error: ObjValueAny) => {
    if (!navigator.onLine) {
        ElMessage.closeAll();
        ElMessage.error('网络未连接');
        return Promise.reject(error.response);
    }
    if (error.code === 'ERR_CANCELED') {
        return Promise.reject('中止请求');
    } else if (error.response) {
        const { data } = error.response || {};

        if (data.msg && data.code !== layoutCode) {
            return Promise.resolve(data);
        }
        if (error.response.status >= 500) {
            ElMessage.closeAll();
            ElMessage.error(error.message);
        }
        return Promise.reject(error.response);
    }
})

function logoutMessage(data: ObjValueAny) {
    if (data.code === layoutCode) {
        ElMessage.closeAll();
        if (showMsg) {
            ElMessage.error(data.msg);
            router.push('/login');
            showMsg = false;
            setTimeout(() => {
                showMsg = true;
            }, 3000);
        }
    }
}

export default service;